package com.facebook.presto.tdengine;

import com.facebook.presto.common.type.*;
import com.facebook.presto.spi.ColumnMetadata;
import com.taosdata.jdbc.TSDBConstants;
import com.taosdata.jdbc.rs.RestfulDriver;
import com.taosdata.jdbc.utils.StringUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class TdUtil {

    private static Connection conn;


    /**
     * 获取表结构
     *
     * @param conn
     * @param dbName
     * @param tableName
     * @return
     * @throws Exception
     */
    public static List<TdEngineColumn> getColumns(Connection conn, String dbName, String tableName) throws Exception {
        ResultSet columns = conn.getMetaData().getColumns(dbName, "", tableName, "");
        List<TdEngineColumn> list = new ArrayList<>();
        while (columns.next()) {
            String filed = columns.getString(4);
            String type = columns.getString(5);
            String note = columns.getString(12);
            int length = columns.getInt(7);
            TdEngineColumn column = new TdEngineColumn();
            column.setField(filed);
            column.setType(type);
            column.setNote(note);
            column.setLength(length);
            list.add(column);
        }
        return list;
    }

    public static List<TdEngineColumn> getColumns(String dbName, String tableName) throws Exception {
        return getColumns(conn, dbName, tableName);
    }

    /**
     * 获取超级表
     *
     * @param conn
     * @param dbName
     * @return
     * @throws Exception
     */
    public static List<String> getStable(Connection conn, String dbName) throws Exception {
        List<String> tables = new ArrayList<>();
        DatabaseMetaData metaData = conn.getMetaData();
        ResultSet schemas = metaData.getSuperTables(dbName, "", "%%");
        while (schemas.next()) {
            tables.add(schemas.getString(4));
        }
        return tables.stream().filter(t -> !StringUtils.isEmpty(t)).distinct().collect(Collectors.toList());
    }

    public static List<String> getStable(String dbName) throws Exception {
        return getStable(conn, dbName);
    }

    /**
     * 获取数据库
     *
     * @param conn
     * @return
     * @throws Exception
     */
    public static List<String> getDataBases(Connection conn) throws Exception {
        List<String> databases = new ArrayList<>();

        DatabaseMetaData metaData = conn.getMetaData();
        ResultSet catalogs = metaData.getCatalogs();
        while (catalogs.next()) {
            String string = catalogs.getString(1);
            databases.add(string);
        }
        return databases;
    }

    public static List<String> getDataBases() throws Exception {
        return getDataBases(conn);
    }

    public static List<ColumnMetadata> getColumnMetadata(String tableName, String schemaName) throws Exception {
        ResultSet columns = conn.getMetaData().getColumns(schemaName, "", tableName, "");
        List<ColumnMetadata> metadataList = new ArrayList<>();
        while (columns.next()) {
            String filed = columns.getString(4);
            String type = columns.getString(5);
            //  String note = columns.getString(12);
            //   int length = columns.getInt(7);
            String taosTypeName = TSDBConstants.jdbcType2TaosTypeName(Integer.parseInt(type));

            //todo
            ColumnMetadata column = new ColumnMetadata(filed, TdUtil.taosTypeName2PrestoType(taosTypeName));
            metadataList.add(column);
        }
        return metadataList;
    }

    private static Type taosTypeName2PrestoType(String taosTypeName) {
        switch (taosTypeName) {
            case "TIMESTAMP":
                return TimestampType.TIMESTAMP;
            case "INT":
                return IntegerType.INTEGER;
            case "BIGINT":
                return BigintType.BIGINT;
            case "FLOAT":
            case "DOUBLE":
                return DoubleType.DOUBLE;
            case "SMALLINT":
                return SmallintType.SMALLINT;
            case "TINYINT":
                return TinyintType.TINYINT;
            case "BOOL":
                return BooleanType.BOOLEAN;
            case "NCHAR":
            case "BINARY":
            default:
                return VarcharType.createUnboundedVarcharType();
        }
    }

    //todo
    public static Iterator<TdEngineRow> select(String tableName, String schemaName) throws Exception {
        List<TdEngineRow> list = new ArrayList<>();
        List<ColumnMetadata> columns = getColumnMetadata(tableName, schemaName);
        List<String> tags = new ArrayList<String>();
        for (ColumnMetadata column : columns) {
            tags.add(column.getName());
        }

        return list.iterator();
    }

    public static void init(String jdbcUrl) throws Exception {
        DriverManager.registerDriver(new RestfulDriver());
        conn = DriverManager.getConnection(jdbcUrl);
    }
}
